/*
 * Copyright (C) 2025 Tsingteng MicroSystem
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <ctype.h>
#include "osi_config_parser.h"

/**
 * @file osi_parser.c
 * @brief config文件解析相关API
*/

#define CF_PARSE_BUF_LEN 256
#define CF_PARSE_KEY_BUF_LEN 128
#define CF_PARSE_VALUE_BUF_LEN 1024

/**
 * @brief 配置解析上下文结构体
 */
typedef struct {
    bool multi_line; // 是否多行模式
    char line[CF_PARSE_BUF_LEN]; // 当前处理的行
    uint16_t line_num; // 当前行号
    uint16_t err_sum; // 错误计数
    char key_buf[CF_PARSE_KEY_BUF_LEN]; // 键缓冲区
    char value_buf[CF_PARSE_VALUE_BUF_LEN]; // 值缓冲区
    size_t value_len; // 值长度
    tNFC_CF_PARAM *table; // 配置项列表
    size_t table_len; // 配置项数量
} tNFC_PARSE_CTX;

/**
 * @brief 将给定的配置项参数解析为布尔值。
 *
 * 将字符串形式的布尔值解析为bool类型。
 * 支持的值包括"true"、"false"、"1"和"0"（不区分大小写）。
 *
 * @param value 字符串形式的布尔值。
 * @param value_ptr 指向存储解析结果的bool变量的指针。
 *
 * @return 解析成功返回true，失败返回false。
 */
static bool parse_bool(char *value, bool *value_ptr)
{
    OSI_CHK_PARAM_INVALID(!value, return false);
    OSI_CHK_PARAM_INVALID(!value_ptr, return false);
    OSI_CHK_PARAM_INVALID(value[0] == '\0', return false);

    if (strcasecmp(value, "true") == 0 || strcmp(value, "1") == 0) {
        *value_ptr = true;
        return true;
    }
    if (strcasecmp(value, "false") == 0 || strcmp(value, "0") == 0) {
        *value_ptr = false;
        return true;
    }
    NFCLOG_E("Invalid bool value: %s", value);
    return false;
}


/**
 * @brief 将给定的配置项参数解析为 uint8_t 类型的值。
 *
 * 将字符串形式的数值解析为 uint8_t 类型。
 *
 * @param value 字符串指针，表示要解析的值。
 * @param value_ptr 指向存储解析结果的 uint8_t 变量的指针。
 *
 * @return 解析成功返回 true，失败返回 false。
 */
static bool parse_uint8(char *value, uint8_t *value_ptr)
{
    OSI_CHK_PARAM_INVALID(!value, return false);
    OSI_CHK_PARAM_INVALID(!value_ptr, return false);

    char *endptr = NULL;

    errno = 0;
    long val = strtol(value, &endptr, 0);
    if (endptr == value || errno != 0 || val < 0 || val > UINT8_MAX) {
        NFCLOG_E("Invalid uint8_t value: %s", value);
        return false;
    }
    if (*endptr != '\0' && strchr(" \t\n\r\f\v", *endptr) == NULL) {
        NFCLOG_E("Unexpected characters after uint8_t value: %s", value);
        return false;
    }
    *value_ptr = (uint8_t)val;
    return true;
}

/**
 * @brief 将给定的配置项参数解析为 uint16_t 类型的值。
 *
 * 将字符串形式的数值解析为 uint16_t 类型。
 *
 * @param value 字符串指针，表示要解析的值。
 * @param value_ptr 指向存储解析结果的 uint16_t 变量的指针。
 *
 * @return 解析成功返回 true，失败返回 false。
 */
static bool parse_uint16(char *value, uint16_t *value_ptr)
{
    OSI_CHK_PARAM_INVALID(!value, return false);
    OSI_CHK_PARAM_INVALID(!value_ptr, return false);

    char *endptr = NULL;

    errno = 0;
    long val = strtol(value, &endptr, 0);
    if (endptr == value || errno != 0 || val < 0 || val > UINT16_MAX) {
        NFCLOG_E("Invalid uint16_t value: %s", value);
        return false;
    }
    if (*endptr != '\0' && strchr(" \t\n\r\f\v", *endptr) == NULL) {
        NFCLOG_E("Unexpected characters after uint16_t value: %s", value);
        return false;
    }
    *value_ptr = (uint16_t)val;
    return true;
}

/**
 * @brief 将给定的字符串值解析为 uint32_t 类型。
 *
 * 将字符串形式的数值解析为 uint32_t 类型。
 *
 * @param value 字符串指针，表示要解析的值。
 * @param value_ptr 指向存储解析结果的 uint32_t 变量的指针。
 *
 * @return 解析成功返回 true，失败返回 false。
 */
static bool parse_uint32(char *value, uint32_t *value_ptr)
{
    OSI_CHK_PARAM_INVALID(!value, return false);
    OSI_CHK_PARAM_INVALID(!value_ptr, return false);

    char *endptr = NULL;

    errno = 0;
    long val = strtol(value, &endptr, 0);
    if (endptr == value || errno != 0 || val < 0 || val > UINT32_MAX) {
        NFCLOG_E("Invalid uint32_t value: %s", value);
        return false;
    }
    if (*endptr != '\0' && strchr(" \t\n\r\f\v", *endptr) == NULL) {
        NFCLOG_E("Unexpected characters after uint32_t value: %s", value);
        return false;
    }
    *value_ptr = (uint32_t)val;
    return true;
}

/**
 * @brief 解析字符串类型的配置项，去除首尾的双引号，并将结果存储到指定的内存地址。
 *
 * 该函数将输入的字符串配置项去除首尾的双引号，并将处理后的字符串复制到指定的内存地址。
 * 如果输入字符串不包含双引号，则直接复制字符串。
 *
 * @param value 输入的字符串指针，表示要解析的配置项值。
 * @param p_value_ptr 指向目标内存地址的指针，用于存储解析后的字符串。
 *
 * @return 解析成功返回 true，否则返回 false。如果内存分配失败，也会返回 false。
 */
static bool parse_string(char *value, char **p_value_ptr)
{
    OSI_CHK_PARAM_INVALID(!value, return false);
    OSI_CHK_PARAM_INVALID(!p_value_ptr, return false);

    if (*p_value_ptr) {
        osi_free(*p_value_ptr);
    }

    value += strspn(value, "\"");
    char *end = value + strlen(value);
    end -= strspn(end - 1, "\"");
    if (end < value) {
        NFCLOG_E("Invalid array format: %s", value);
        return false;
    }
    *end = '\0';

    size_t len = end - value;
    char *str = osi_calloc(len + 1);
    if (str == NULL) {
        NFCLOG_E("Failed to allocate memory for string");
        return false;
    }
    *p_value_ptr = str;
    (void) osi_strncpy(str, len + 1, value, len);
    return true;
}

/**
 * @brief 提取大括号{}之间的内容，去除前后空白字符
 * @param value 输入字符串
 * @return 处理后的字符串起始位置，失败返回NULL
 */
static char* preprocess_array_string(char *value)
{
    OSI_CHK_PARAM_INVALID(!value, return NULL);

    // 先找到 '{' 的位置
    char *start = strchr(value, '{');
    if (!start) {
        return NULL;
    }

    // 跳过 '{'
    start++;
    // 跳过 '{' 后的空白
    start += strspn(start, " \t\r\n");
    // 找到 '}' 的位置
    size_t content_len = strcspn(start, "}");
    if (start[content_len] != '}') {
        return NULL;
    }

    // 移除结尾空白
    char *end = start + content_len;
    while (end > start && isspace((unsigned char)*(end - 1))) {
        end--;
    }

    OSI_CHK_PARAM_INVALID(end <= start, return NULL);
    *end = '\0';
    return start;
}

/**
 * @brief 计算数组中元素的个数
 *
 * @param value 预处理后的字符串
 * @return 元素个数
 */
static size_t count_array_elements(const char *value)
{
    OSI_CHK_PARAM_INVALID(!value, return 0);

    size_t count = 0;
    const char *ptr = value;

    while (*ptr) {
        // 跳过分隔符和空白字符
        while (*ptr && (isspace((unsigned char)*ptr) || *ptr == ',' || *ptr == ':')) {
            ptr++;
        }

        if (*ptr) {
            count++;
            // 跳过当前元素
            while (*ptr && !isspace((unsigned char)*ptr) && *ptr != ',' && *ptr != ':') {
                ptr++;
            }
        }
    }

    return count;
}

/**
 * @brief 解析单个十六进制字符串为uint8_t值
 *
 * @param token 要解析的字符串
 * @param value 输出参数，存储解析结果
 * @return 解析成功返回true，否则返回false
 */
static bool parse_single_uint8(const char *token, uint8_t *value)
{
    if (!token || !value) {
        return false;
    }

    errno = 0;
    char *endptr = NULL;

    // 判断是否为十六进制格式（0x开头）
    long val;
    if (token[0] == '0' && (token[1] == 'x' || token[1] == 'X')) {
        val = strtol(token + CF_HEX_PREFIX_OFFSET, &endptr, CF_PARSE_HEX_BASE);
    } else {
        val = strtol(token, &endptr, CF_PARSE_HEX_BASE);
    }

    // 检查转换错误
    if (errno == ERANGE) {
        NFCLOG_E("Value out of range: %s", token);
        return false;
    }

    if (val < 0 || val > UINT8_MAX) {
        NFCLOG_E("Invalid uint8_t value: %s", token);
        return false;
    }

    // 检查是否有无效字符
    if (*endptr != '\0' && !isspace((unsigned char)*endptr)) {
        NFCLOG_E("Unexpected characters after uint8_t value: %s", token);
        return false;
    }

    *value = (uint8_t)val;
    return true;
}

/**
 * @brief 解析所有数组元素
 *
 * @param value 预处理后的字符串
 * @param data 输出数组
 * @param count 元素个数
 * @return 解析成功返回true，否则返回false
 */
static bool parse_all_elements(char *value, uint8_t *data, size_t count)
{
    if (!value || !data) {
        return false;
    }

    char *save_ptr = NULL;
    char *token = strtok_r(value, ",: \t\r\n", &save_ptr);
    size_t index = 0;

    while (token && index < count) {
        if (!parse_single_uint8(token, &data[index])) {
            return false;
        }

        index++;
        token = strtok_r(NULL, ",: \t\r\n", &save_ptr);
    }

    return true;
}

/**
 * @brief 将给定的配置项参数字符串解析为字节数组，并存储到指定的内存地址中
 *
 * 该函数将输入的字符串解析为字节数组。输入字符串应使用大括号 {} 包裹，元素之间使用逗号 , 或空格或换行符分隔。
 * 例如："{0x01, 0x02, 0x03}" 或 "{0x01 0x02, 0x03}"。
 * 解析成功后，会分配动态内存存储解析结果，调用者需要负责释放这块内存。
 *
 * @param value 输入的字符串指针，表示要解析的配置项值。
 * @param value_ptr 指向 tNFC_CF_ARRAY 结构体的指针，用于存储解析后的数组。
 *                      其中，data 字段将指向动态分配的内存，len 字段将存储数组的长度。
 *
 * @return 解析成功返回 true，否则返回 false。如果内存分配失败，也会返回 false。
 */
static bool parse_array(char *value, tNFC_CF_ARRAY *value_ptr)
{
    OSI_CHK_PARAM_INVALID(!value, return false);
    OSI_CHK_PARAM_INVALID(!value_ptr, return false);

    // 清理之前的数据
    if (value_ptr->inner_data) {
        osi_free(value_ptr->inner_data);
        value_ptr->inner_data = NULL;
    }

    // 预处理输入字符串
    char *preprocessed_value = preprocess_array_string(value);
    if (!preprocessed_value) {
        NFCLOG_E("Invalid array format: %s", preprocessed_value);
        return false;
    }

    // 计算元素个数
    size_t count = count_array_elements(preprocessed_value);
    if (count == 0) {
        value_ptr->len = 0;
        return true;
    }

    // 分配内存
    value_ptr->inner_data = (uint8_t *)osi_calloc(count * sizeof(uint8_t));
    if (!value_ptr->inner_data) {
        NFCLOG_E("Failed to allocate memory for array");
        return false;
    }

    // 解析所有元素
    if (!parse_all_elements(preprocessed_value, value_ptr->inner_data, count)) {
        osi_free(value_ptr->inner_data);
        value_ptr->inner_data = NULL;
        return false;
    }

    value_ptr->len = count;
    return true;
}

/**
 * @brief 检查配置文件行的格式是否正确。
 * 该函数检查配置文件的每一行，确保其格式正确，包括：
 * 1. 行不能为空。
 * 2. 行尾不应该包含CRLF，只允许LF。
 * 3. 行长度不能超过缓冲区大小。
 * 4. 去除行首和行尾的空格和制表符。
 *
 * @param line 行缓冲区
 * @param line_num 行号
 *
 * @return 如果行格式正确，返回true；否则返回false。
 */
static bool line_format_check(char *line, uint16_t line_num)
{
    size_t len = strlen(line);
    if (len <= 0) {
        NFCLOG_E("Config file line %u is empty", line_num);
        return false;
    } else if (len >= CF_PARSE_BUF_LEN - 1) {
        if (line[len - 1] == '\r') {
            line[len - 1] = '\n';
        }
        if (line[len - 1] != '\n') {
            NFCLOG_E("Config file line %u too long", line_num);
            return false;
        }
    }

    char *trimmed_line = line;
    char *new_line = line;
    while (*trimmed_line) {
        if (*trimmed_line != ' ' && *trimmed_line != '\t' &&
            *trimmed_line != '\r' && *trimmed_line != '\n') {
            *new_line++ = *trimmed_line;
        }
        trimmed_line++;
    }
    *new_line = '\0';

    return true;
}

/**
 * @brief 解析配置项的字符串值
 *
 * 根据配置项的类型，将字符串值解析为相应的数据类型，并存储到配置项结构体中。
 *
 * @param[in] value 字符串值
 * @param[in] item 配置项结构体指针
 *
 * @return 解析成功返回 true，失败返回 false。
 */
bool osi_config_parse_item(char *value, tNFC_CF_PARAM *item)
{
    OSI_CHK_PARAM_INVALID(!value, return false);
    OSI_CHK_PARAM_INVALID(!item, return false);

    switch (item->type) {
        case BOOL_TYPE:
            return parse_bool(value, item->p_BOOL_TYPE);
        case UINT8_TYPE:
            return parse_uint8(value, item->p_UINT8_TYPE);
        case UINT16_TYPE:
            return parse_uint16(value, item->p_UINT16_TYPE);
        case UINT32_TYPE:
            return parse_uint32(value, item->p_UINT32_TYPE);
        case STRING_TYPE:
            return parse_string(value, item->p_STRING_TYPE);
        case ARRAY_TYPE:
            return parse_array(value, item->p_ARRAY_TYPE);
        default:
            NFCLOG_E("Invalid type: %d", item->type);
    }

    return false;
}

/**
 * @brief 处理字符串类型的默认值设置
 *
 * @param config_item 配置项参数
 * @param default_str 默认字符串值
 *
 * @return 处理结果，成功返回true，失败返回false
 */
static bool handle_string_default(tNFC_CF_PARAM *config_item, const char *default_str)
{
    if (default_str == NULL) {
        return true;
    }

    size_t default_str_len = strlen(default_str);
    char *allocated_str = osi_calloc(default_str_len + 1);
    if (!allocated_str) {
        NFCLOG_E("Malloc %s default string failed", config_item->key);
        return false;
    }

    osi_strncpy(allocated_str, default_str_len + 1, default_str, default_str_len);
    *config_item->p_STRING_TYPE = allocated_str;
    return true;
}

/**
 * @brief 处理数组类型的默认值设置
 *
 * @param config_item 配置项参数
 *
 * @return 处理结果，成功返回true，失败返回false
 */
static bool handle_array_default(tNFC_CF_PARAM *config_item)
{
    if (config_item->d_ARRAY_TYPE == NULL) {
        return true;
    }

    size_t default_str_len = strlen(config_item->d_ARRAY_TYPE);
    char *default_str = osi_calloc(default_str_len + 1);
    if (!default_str) {
        NFCLOG_E("Malloc %s default array failed", config_item->key);
        return false;
    }

    osi_strncpy(default_str, default_str_len + 1,
                  config_item->d_ARRAY_TYPE, default_str_len);

    bool ret = osi_config_parse_item(default_str, config_item);
    osi_free(default_str);

    if (!ret) {
        NFCLOG_E("Set %s default array value failed", config_item->key);
        return false;
    }

    return true;
}

/**
 * @brief 处理单个配置项的默认值设置
 *
 * @param config_item 配置项参数
 *
 * @return 处理结果，成功返回true，失败返回false
 */
static bool set_single_config_default(tNFC_CF_PARAM *config_item)
{
    bool ret = true;
    switch (config_item->type) {
        case BOOL_TYPE:
            *config_item->p_BOOL_TYPE = config_item->d_BOOL_TYPE;
            break;

        case UINT8_TYPE:
            *config_item->p_UINT8_TYPE = config_item->d_UINT8_TYPE;
            break;

        case UINT16_TYPE:
            *config_item->p_UINT16_TYPE = config_item->d_UINT16_TYPE;
            break;

        case UINT32_TYPE:
            *config_item->p_UINT32_TYPE = config_item->d_UINT32_TYPE;
            break;

        case STRING_TYPE:
            ret = handle_string_default(config_item, config_item->d_STRING_TYPE);
            break;

        case ARRAY_TYPE:
            ret = handle_array_default(config_item);
            break;

        default:
            NFCLOG_E("Invalid type: %d", config_item->type);
            ret = false;
            break;
    }
    return ret;
}

/**
 * @brief 解析配置项默认值
 *
 * 该函数遍历配置项列表，为各种类型的配置项解析并设置默认值。
 *
 * @param lists     配置项参数列表数组。
 * @param list_num  配置项参数列表数组的元素数量。
 *
 * @return 解析结果状态码，成功返回true，失败返回false。
 */
bool osi_config_set_defaults(tNFC_CF_PARAM *table, size_t table_len)
{
    OSI_CHK_PARAM_INVALID(!table, return false);

    for (size_t index = 0; index < table_len; index++) {
        if (!set_single_config_default(&table[index])) {
            return false;
        }
    }

    return true;
}

/**
 * @brief 检查并跳过无效行（注释行和空行）
 * @param line 待检查的行
 * @return true表示需要跳过，false表示需要处理
 */
static bool should_skip_line(const char *line)
{
    return (line[0] == '#' || strspn(line, " \t\r\n") == strlen(line));
}

/**
 * @brief 解析单行键值对
 * @param line 输入行
 * @param key 输出键指针
 * @param value 输出值指针
 * @param save_ptr strtok_r的保存指针
 * @return true表示解析成功，false表示失败
 */
static bool parse_key_value(char *line, char **key, char **value, char **save_ptr)
{
    *key = strtok_r(line, "=", save_ptr);
    *value = strtok_r(NULL, "=", save_ptr);
    return (*key != NULL && *value != NULL);
}

/**
 * @brief 检查是否是跨行值的开始
 * @param value 值字符串
 * @return true表示是跨行值开始
 */
static bool is_multiline_start(const char *value)
{
    return (strchr(value, '{') != NULL && strchr(value, '}') == NULL);
}

/**
 * @brief 处理跨行值的开始
 * @param key 键
 * @param value 值
 * @param key_buf 键缓冲区
 * @param value_buf 值缓冲区
 * @param value_len 值长度指针
 */
static bool start_multiline_value(const char *key, const char *value,
                                  char *key_buf, char *value_buf, size_t *value_len)
{
    if (!osi_strncpy(key_buf, CF_PARSE_KEY_BUF_LEN - 1, key, CF_PARSE_KEY_BUF_LEN - 1)) {
        return false;
    }

    key_buf[CF_PARSE_KEY_BUF_LEN - 1] = '\0';
    *value_len = strlen(value);

    if (!osi_strncpy(value_buf, CF_PARSE_VALUE_BUF_LEN - 1, value, *value_len)) {
        return false;
    }

    value_buf[*value_len] = '\0';
    return true;
}

/**
 * @brief 处理跨行值的拼接
 * @param line 当前行
 * @param value_buf 值缓冲区
 * @param value_len 当前值长度指针
 * @return true表示拼接成功，false表示缓冲区溢出
 */
static bool append_multiline_value(const char *line, char *value_buf, size_t *value_len)
{
    size_t current_len = strlen(line);
    if (*value_len + current_len >= CF_PARSE_VALUE_BUF_LEN - 1) {
        return false;
    }

    if (!osi_strncat(value_buf, CF_PARSE_VALUE_BUF_LEN, line, current_len)) {
        return false;
    }

    *value_len += current_len;
    return true;
}

/**
 * @brief 检查跨行值是否结束
 * @param line 当前行
 * @return true表示跨行值结束
 */
static bool is_multiline_end(const char *line)
{
    return (strchr(line, '}') != NULL);
}

/**
 * @brief 解析并设置配置项
 * @param key 键
 * @param value 值
 * @param table 配置项列表
 * @param table_len 配置项数量
 * @return true表示找到匹配项，false表示未找到或解析失败
 */
static bool parse_and_set_config(const char *key, char *value,
                                 tNFC_CF_PARAM *table, size_t table_len)
{
    for (size_t index = 0; index < table_len; index++) {
        if (strcmp(key, table[index].key) == 0) {
            if (osi_config_parse_item(value, &table[index])) {
                table[index].present = true;
                return true;
            }
            return false; // 找到匹配的键但解析失败
        }
    }
    return true; // 未找到匹配的键，按原逻辑不增加错误计数
}

/**
 * @brief 处理多行模式的配置
 * @param ctx 解析上下文
 * @param key 键指针
 * @param value 值指针
 * @return true表示继续处理,false表示返回
 */
static bool process_multiline_mode(tNFC_PARSE_CTX *ctx, char **key, char **value)
{
    if (!append_multiline_value(ctx->line, ctx->value_buf, &ctx->value_len)) {
        NFCLOG_E("Value too long for key '%s'", ctx->key_buf);
        ctx->err_sum = 0xFFFF;
        return false;
    }

    if (!is_multiline_end(ctx->line)) {
        return false;
    }

    ctx->multi_line = false;
    *key = ctx->key_buf;
    *value = ctx->value_buf;
    return true;
}

/**
 * @brief 处理单行模式的配置
 * @param ctx 解析上下文
 * @param key 键指针
 * @param value 值指针
 * @param save_ptr strtok_r的保存指针
 * @return true表示继续处理,false表示返回
 */
static bool process_singleline_mode(tNFC_PARSE_CTX *ctx, char **key, char **value, char **save_ptr)
{
    if (!parse_key_value(ctx->line, key, value, save_ptr)) {
        NFCLOG_E("Invalid line %u, key is %s, value is %s", ctx->line_num,
                 *key == NULL ? "NULL" : *key,
                 *value == NULL ? "NULL" : *value);
        ctx->err_sum++;
        return false;
    }

    if (is_multiline_start(*value)) {
        ctx->multi_line = true;
        if (!start_multiline_value(*key, *value, ctx->key_buf, ctx->value_buf, &ctx->value_len)) {
            ctx->err_sum++;
            return false;
        }
        return false;
    }

    return true;
}

/**
 * @brief 处理单行配置
 * @param ctx 解析上下文
 */
static void process_config_line(tNFC_PARSE_CTX *ctx)
{
    char *key = NULL;
    char *value = NULL;
    char *save_ptr = NULL;

    // 跳过注释行和空行
    if (should_skip_line(ctx->line)) {
        return;
    }

    // 检查行格式
    if (!line_format_check(ctx->line, ctx->line_num)) {
        ctx->err_sum = 0xFFFF;
        return;
    }

    // 根据模式处理配置
    bool should_continue;
    if (ctx->multi_line) {
        should_continue = process_multiline_mode(ctx, &key, &value);
    } else {
        should_continue = process_singleline_mode(ctx, &key, &value, &save_ptr);
    }

    // 如果需要继续处理且不是多行模式,则解析配置项
    if (should_continue && !ctx->multi_line) {
        if (!parse_and_set_config(key, value, ctx->table, ctx->table_len)) {
            ctx->err_sum++;
        }
    }
}

/**
 * @brief 解析指定路径的conf配置文件
 *
 * 从给定的文件路径读取conf配置文件，并解析其中的配置项。
 * 对于每一行配置，解析键值对，并根据配置项类型进行解析。
 * 支持跨行配置，使用{}包围跨行值。
 *
 * @param path_name 配置文件的路径
 * @param table 配置项列表
 * @param table_len 配置项数量
 *
 * @return 解析结果状态码，包含解析的行数和错误数量。
 *         解析成功返回错误项为0，并一起返回解析行数。
 */
uint32_t osi_config_parse(const char *path_name, tNFC_CF_PARAM *table, size_t table_len)
{
    OSI_CHK_PARAM_INVALID(!path_name, return nfc_cf_set_status(0xFFFF, 0xFFFF));

    NFCLOG_I("Parse file : %s", path_name);
    FILE *fp = fopen(path_name, "r");
    if (fp == NULL) {
        NFCLOG_E("Failed to open %s", path_name);
        return nfc_cf_set_status(0xFFFF, 0xFFFF);
    }

    tNFC_PARSE_CTX ctx = {0};
    ctx.table = table;
    ctx.table_len = table_len;
    while (fgets(ctx.line, CF_PARSE_BUF_LEN, fp) != NULL) {
        ctx.line_num++;
        process_config_line(&ctx);
        if (ctx.err_sum == 0xFFFF) {
            break;
        }

        // 重置键值缓冲区
        if (!ctx.multi_line) {
            osi_memset(ctx.key_buf, CF_PARSE_KEY_BUF_LEN, 0, CF_PARSE_KEY_BUF_LEN);
            osi_memset(ctx.value_buf, CF_PARSE_VALUE_BUF_LEN, 0, CF_PARSE_VALUE_BUF_LEN);
            ctx.value_len = 0;
        }
    }

    // 检查是否有未完成的跨行值
    if (ctx.multi_line) {
        NFCLOG_E("Value is broken, line %u", ctx.line_num);
    }

    if (fclose(fp) != 0) {
        NFCLOG_W("Warning: Failed to close file %s", path_name);
    }
    return nfc_cf_set_status(ctx.line_num, ctx.err_sum);
}

/**
 * @brief 重置基本类型的配置项值
 * @param item 配置项
 */
static void reset_basic_config_value(tNFC_CF_PARAM *item)
{
    switch (item->type) {
        case BOOL_TYPE:
            *item->p_BOOL_TYPE = false;
            break;
        case UINT8_TYPE:
            *item->p_UINT8_TYPE = 0;
            break;
        case UINT16_TYPE:
            *item->p_UINT16_TYPE = 0;
            break;
        case UINT32_TYPE:
            *item->p_UINT32_TYPE = 0;
            break;
        default:
            break;
    }
}

/**
 * @brief 释放数组类型的配置项内存
 * @param item 配置项
 */
static void free_array_config(tNFC_CF_PARAM *item)
{
    OSI_CHK_PARAM_INVALID(!item->p_ARRAY_TYPE, return);

    if (!item->p_ARRAY_TYPE->inner_data) {
        return;
    }

    NFCLOG_D("Free %s array value", item->key);
    item->p_ARRAY_TYPE->len = 0;
    osi_free(item->p_ARRAY_TYPE->inner_data);
    item->p_ARRAY_TYPE->inner_data = NULL;
}

/**
 * @brief 释放字符串类型的配置项内存
 * @param item 配置项
 */
static void free_string_config(tNFC_CF_PARAM *item)
{
    OSI_CHK_PARAM_INVALID(!item->p_STRING_TYPE, return);

    if (!*item->p_STRING_TYPE) {
        return;
    }

    NFCLOG_D("Free %s string value", item->key);
    osi_free(*item->p_STRING_TYPE);
    *item->p_STRING_TYPE = NULL;
}

/**
 * @brief 释放配置参数列表中的动态分配内存
 *
 * 此函数主要完成以下操作：
 * 1. 释放配置参数列表中动态分配的内存，包括数组类型和字符串类型的配置项。
 * 2. 将相关指针置为NULL，并重置present标志，防止悬空指针或脏数据。
 *
 * @param table     配置参数列表指针，包含需要释放内存的配置项
 * @param table_len  配置参数列表中的配置项数量
 */
void osi_config_unparse(tNFC_CF_PARAM *table, size_t table_len)
{
    OSI_CHK_PARAM_INVALID(!table || table_len == 0, return);

    NFCLOG_D("Free config and clear struct");
    for (size_t i = 0; i < table_len; i++) {
        table[i].present = false;

        switch (table[i].type) {
            case ARRAY_TYPE:
                free_array_config(&table[i]);
                break;
            case STRING_TYPE:
                free_string_config(&table[i]);
                break;
            default:
                reset_basic_config_value(&table[i]);
                break;
        }
    }
}

/**
 * @brief 根据类型获取配置项的值和大小
 * @param item 配置项
 * @param pp_value 返回值指针
 * @param value_size 返回值大小
 * @return 成功返回true，失败返回false
 */
static bool get_config_value_by_type(tNFC_CF_PARAM *item,
                                     const void **pp_value,
                                     size_t *value_size)
{
    switch (item->type) {
        case BOOL_TYPE:
            *pp_value = item->p_BOOL_TYPE;
            *value_size = sizeof(bool);
            break;
        case UINT8_TYPE:
            *pp_value = item->p_UINT8_TYPE;
            *value_size = sizeof(uint8_t);
            break;
        case UINT16_TYPE:
            *pp_value = item->p_UINT16_TYPE;
            *value_size = sizeof(uint16_t);
            break;
        case UINT32_TYPE:
            *pp_value = item->p_UINT32_TYPE;
            *value_size = sizeof(uint32_t);
            break;
        case STRING_TYPE:
            *pp_value = *item->p_STRING_TYPE;
            *value_size = strlen(*item->p_STRING_TYPE);
            break;
        case ARRAY_TYPE:
            *pp_value = item->p_ARRAY_TYPE->data;
            *value_size = item->p_ARRAY_TYPE->len;
            break;
        default:
            NFCLOG_E("Unsupported type: %d", item->type);
            return false;
    }
    return true;
}

/**
 * @brief 检查指定的键值是否存在于配置中，并返回对应的值
 *
 * @param[in] table 配置参数列表
 * @param[in] table_len 配置参数列表的长度
 * @param[in] key 配置项的键，用于在配置列表中查找对应的配置项
 * @param[out] pp_value 返回指向键对应配置项值的指针
 * @param[out] value_size 返回键对应配置项值大小的指针
 *
 * @return 如果成功找到配置项并复制其值的指针，返回true；否则返回false
 */
bool osi_config_get_value_present(tNFC_CF_PARAM *table, size_t table_len,
                                  const char *key, const void **pp_value,
                                  size_t *value_size)
{
    OSI_CHK_PARAM_INVALID(!table || !key, return false);

    // 查找匹配的配置项
    tNFC_CF_PARAM *found_item = NULL;
    for (size_t i = 0; i < table_len; i++) {
        if (strcmp(table[i].key, key) == 0) {
            found_item = &table[i];
            break;
        }
    }

    // 检查是否找到配置项
    if (!found_item) {
        return false;
    }

    // 检查配置项是否已设置
    if (!found_item->present) {
        NFCLOG_W("\"%s\" not set in config file", key);
        return false;
    }

    // 如果只需检查存在性
    if (!pp_value && !value_size) {
        NFCLOG_D("\"%s\" is exist in config", key);
        return true;
    }

    // 检查输出参数
    if (!pp_value || !value_size) {
        NFCLOG_E("Invalid output params");
        return false;
    }

    // 获取配置值
    if (!get_config_value_by_type(found_item, pp_value, value_size)) {
        return false;
    }

    NFCLOG_D("Get \"%s\" value success", key);
    return true;
}
